var templates = [];

jQuery.fn.reverse = function() {
    return this.pushStack(this.get().reverse(), arguments);
};


function processRequest(_this, requestConf)
{					
	var queryName = requestConf['from'];
	var fluctuateId = parseInt( _this.attr('fluctuateId') );
	var element = _this;
	var postObj = {};
	
	if( _this.parents('*[post-data]').length )
	{
		_this.parents('*[post-data]').reverse().each(function(){
			
			var nObj = eval('({'+$(this).attr('post-data')+'})');
			
			postObj = $.extend(postObj, nObj);
		});
	}
	
	if( _this.attr('post-data') !== undefined )
	{
		var nObj = eval('({'+_this.attr('post-data')+'})');
		
		postObj = $.extend(postObj, nObj);
	}
	
	postObj.fluctuate = queryName;
	
	$.post(
		'fluctuate.php',
		postObj,
		function( incomingPacket ){
			
			var dataLength = 0;
			for (k in incomingPacket.data) if (incomingPacket.data.hasOwnProperty(k)) dataLength++;
			
			if( ! templates[fluctuateId] )
				templates[fluctuateId] = element.clone();
			
			var workingElement = element.clone();
			
			workingElement.children().remove();
			
			var toParse;
			
			if( typeof( incomingPacket.data ) != 'object' )
			{
				toParse = templates[fluctuateId].clone();
				
				toParse.html( incomingPacket.data );
				
				workingElement.append( toParse );
			
			} else {
				
				var cnt = 0;
				
				for(var rowId in incomingPacket.data)
				{
					toParse = templates[fluctuateId].clone();
					
					if( typeof( incomingPacket.data[rowId] ) != 'object' ) // if not object
					{
						if( templates[fluctuateId].attr('value') == '@this' )
						{
							if( toParse.is('input') )
								toParse.val( incomingPacket.data[rowId] );
							else
								toParse.html( incomingPacket.data[rowId] );
							
							element.replaceWith(toParse);
							return;
							
						} else if( $('*[value=\'@this\']', templates[fluctuateId]).length ) {
							
							$('*[value=\'@this\']', toParse).each(function(){
								if( $(this).is('input') )
									$(this).val( incomingPacket.data[rowId] );
								else
									$(this).html( incomingPacket.data[rowId] );
							});
						}
						
					} else {                                                 // else, if object
						
						for(var fieldName in incomingPacket.data[rowId])
						{
							if( templates[fluctuateId].attr('value') == '@this.'+fieldName )
							{
								if( toParse.is('input') )
									toParse.val( incomingPacket.data[rowId][fieldName] );
								else
									toParse.html( incomingPacket.data[rowId][fieldName] );
									
								element.replaceWith(toParse);
								return;
								
							} else if( $('*[value=\'@this.'+fieldName+'\']', templates[fluctuateId]).length ) {
									
								$('*[value=\'@this.'+fieldName+'\']', toParse).each(function(){
									
									if( $(this).is('input') )
										$(this).val( incomingPacket.data[rowId][fieldName] );
									else
										$(this).html( incomingPacket.data[rowId][fieldName] );
								});
							}

						}
					
					}
					
					/* CSS Helpers */
					
					$('*[class^=\'@\']', toParse).each(function(){
						
						if( $(this).hasClass('@parity') )
							$(this).addClass( cnt%2?'odd':'even' ).removeClass('@parity');
							
						if( $(this).hasClass('@index') )
						{
							if( cnt == 0 )
								$(this).addClass('i'+cnt+' first').removeClass('@index');
							else if( cnt == dataLength -1 )
								$(this).addClass('i'+cnt+' last').removeClass('@index');
							else
								$(this).addClass('i'+cnt).removeClass('@index');
						}
					});
					
					cnt++;
					
					workingElement.append( toParse.children() );
				}
			}
			
			element.html( workingElement.children() );
		},
		'json'
	);
}

fluctuate = function()
{
	$('*[ajax]').each(function(){
				
		var form = $(this).closest('form');
		
		form.submit(function() { return false; });
		
		if( $(this).is('a') )
			$(this).attr('href','javascript:void(0);');
	});
	
	$('*[ajax]').live('click', function(){
		
		var form = $(this).closest('form').addClass('loading saving');
		
		$.post(
		form.attr('action'),
		form.serialize(),
		function( response ){
			
			form.removeClass('loading saving');
			
		});
		
		return false;
		
	});
	
	$('*[fluctuate]').each(function(index){
		
		$(this).fluctuate('reloadContent');
		
	});
}

$.fn.fluctuate = function(action)
{
	switch(action)
	{
		case 'reloadContent':
			try
			{
				if( $(this).attr('fluctuate') )
				{
					var index = $('*[fluctuate]').index( $(this) );
					
					$(this).attr({'fluctuateId': index});
					
					var requestConf = [];
					var rConf = $.trim( $(this).attr('fluctuate') ).split(',');
					
					for(var i in rConf)
					{
						rConf[i] = rConf[i].split(':');
						
						if( $.trim( rConf[i][0] ) )
							requestConf[ $.trim( rConf[i][0] ) ] = $.trim( rConf[i][1] );
					}
					
					processRequest( $(this), requestConf );
					
					if( requestConf['refresh'] )
					{
						var jThis = $(this);
						setInterval( function(){ jThis.empty(); processRequest(jThis, requestConf); }, parseInt( requestConf['refresh'] ) * 1000 );
					}
				} else {
					throw new Error("An element to apply reloadContent() to MUST have a 'fluctuate' attribute");
				}
			}
			
			catch(error) { if( console ) console.log(error.message); else alert(error.message); }
			
			break;
		
			
			
		default:
			// nothing
			break;
	}
	
	return $(this);
}

$( function() { fluctuate(); } );
